/*
 * This file is part of LangMan.
 *
 * LangMan is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * LangMan is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LangMan.  If not, see <http://www.gnu.org/licenses/>.
 */

package langman.business.data.model;

import com.google.common.base.Strings;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableMap;
import langman.business.data.TranslationException;

import java.util.LinkedHashMap;

public class Key implements Observable {
    private final StringProperty key = new SimpleStringProperty();
    private final ObservableMap<Language, String> translationMap = FXCollections.observableMap(new LinkedHashMap<>());
    private final BooleanProperty dontTranslate = new SimpleBooleanProperty();

    private final DoubleProperty completeness = new SimpleDoubleProperty();
    private final int numberOfLanguages;

    public Key(int numberOfLanguages, String key) {
        this.numberOfLanguages = numberOfLanguages;
        setKey(key);

        InvalidationListener completenessListener = (Observable observable) -> calculateCompleteness();
        translationMap.addListener(completenessListener);
        dontTranslate.addListener(completenessListener);

    }

    private void calculateCompleteness() {
        if (isDontTranslate()) {
            completeness.set(1);
        } else {
            completeness.set(translationMap.size() / (double) numberOfLanguages);
        }
    }


    public StringProperty keyProperty() {
        return key;
    }

    @Override
    public void addListener(InvalidationListener listener) {
        translationMap.addListener(listener);
        key.addListener(listener);
        completeness.addListener(listener);
        dontTranslate.addListener(listener);
    }

    @Override
    public void removeListener(InvalidationListener listener) {
        translationMap.removeListener(listener);
        key.removeListener(listener);
        completeness.removeListener(listener);
        dontTranslate.removeListener(listener);
    }

    public String getKey() {
        return key.get();
    }

    public final void setKey(String key) {
        this.key.set(key);
    }


    public void translate(Language language, String translation) throws TranslationException {
        if (isDontTranslate() && !language.isReference()) {
            throw new TranslationException("Trying to translate while translating is deactivated for key " + getKey());
        }
        if (Strings.isNullOrEmpty(translation)) {
            translationMap.remove(language);
        } else {
            translationMap.put(language, translation);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Key other = (Key) o;
        return getKey().equals(other.getKey());

    }

    @Override
    public int hashCode() {
        return key.hashCode();
    }

    public String getTranslation(Language language) {
        return translationMap.get(language);
    }

    public double getCompleteness() {
        return completeness.get();
    }

    public void setDontTranslate(boolean dontTranslate) {
        this.dontTranslate.set(dontTranslate);
    }

    public boolean isDontTranslate() {
        return dontTranslate.get();
    }

    public BooleanProperty dontTranslateProperty() {
        return dontTranslate;
    }
}
